home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mm / mm-0.90 / help.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-18  |  10.3 KB  |  425 lines

  1. /*
  2.  * Copyright (c) 1986, 1990 by The Trustees of Columbia University in
  3.  * the City of New York.  Permission is granted to any individual or
  4.  * institution to use, copy, or redistribute this software so long as it
  5.  * is not sold for profit, provided this copyright notice is retained.
  6.  */
  7.  
  8. #ifndef lint
  9. static char *rcsid = "$Header: /f/src2/encore.bin/cucca/mm/tarring-it-up/RCS/help.c,v 2.4 90/10/04 18:24:27 melissa Exp $";
  10. #endif
  11.  
  12. /*
  13.  * help.c:
  14.  * get help strings from fancy database file, for MM
  15.  */
  16.  
  17. #include "mm.h"
  18. #include "set.h"
  19. #include "cmds.h"
  20. #include "parse.h"
  21. #include "help.h"
  22.  
  23. hlp_offset *offsets = NULL;        /* indexes into file, strlens */
  24. FILE *helpfp = NULL;
  25. static char buf[BUFSIZ];
  26. static time_t help_time = 0;
  27.  
  28. extern string help_file, help_dir;
  29.  
  30. char *help_subdirs[] = {        /* must appear in order defined */
  31.     "TOP.DIR",                /* by HELP_TOP...HELP_TOPIC */
  32.     "READ.DIR",                /* in help.h */
  33.     "SEND.DIR",
  34.     "TOPICS.DIR",
  35.     "VARS.DIR",
  36. };
  37.  
  38. #define TOPIC_DIR help_subdirs[HELP_TOPIC]
  39.  
  40.  
  41.  
  42. /*
  43.  * cmd_help:
  44.  * give help on a command, or some other topic
  45.  * Note that most of the help strings were stolen from the DEC20 version,
  46.  * with thanks to Mark Crispin, Mike McMahon, and friends...
  47.  */
  48. cmd_help(n)
  49. int n;
  50. {
  51.     int help_mode;
  52.  
  53.     if (mode & MM_SEND)
  54.     help_mode = HELP_SEND;
  55.     else if (mode & MM_READ)
  56.     help_mode = HELP_READ;
  57.     else
  58.     help_mode = HELP_TOP;
  59.  
  60.     return(cmd_help_1(n,help_mode),0);
  61. }
  62.  
  63. cmd_help_1 (n, mode,recurse)
  64. int n;
  65. {
  66.     extern keytab formattab;
  67.     extern string default_read_command, default_send_command;
  68.  
  69.     static fdb cfmfdb = { _CMCFM,        /* confirm for general help */
  70.                   CM_SDH|CM_NLH, NULL, NULL, 
  71.                   "confirm for a brief help message", NULL, NULL };
  72.  
  73.     static fdb formatfdb = { _CMKEY, CM_NLH, nil, 
  74.                    (pdat) &formattab, "format, " };
  75.  
  76.     static keywrd concept_keys[] = {
  77.     { "CCMD", 0, (keyval) HLP_CCMD },
  78.     { "command-completion", 0, (keyval) HLP_CCMD },
  79.         { "message-sequence", 0 , (keyval) HLP_MESSAGE_SEQUENCE },
  80.     { "mm-initialization-file", 0, (keyval) HLP_MMINIT },
  81.     { "mminit", 0, (keyval) HLP_MMINIT },
  82.     };
  83.     static keytab concepttab = { sizeof (concept_keys) / sizeof (keywrd),
  84.                   concept_keys };
  85.     static fdb conceptfdb = { _CMKEY, CM_NLH, nil, 
  86.                 (pdat) &concepttab, "concept, "};
  87.  
  88.                     /* use to lookup the help files */
  89.     static fdb topic_filfdb = { _CMFIL, FIL_WLD, nil, nil, nil, nil, nil,
  90.                     nil };
  91.     static fdb topicfdb = { _CMKEY, CM_NLH|KEY_PTR, nil, nil,
  92.                 "other topic, ", nil, nil, nil };
  93.  
  94.     static keywrd mode_keys[] = { 
  95.     { "top-level-mode", 0, (keyval) HELP_TOP },
  96.     { "read-mode", 0, (keyval) HELP_READ },
  97.     { "send-mode", 0, (keyval) HELP_SEND },
  98.     };
  99.     static keytab modetab = { sizeof(mode_keys)/sizeof(keywrd), mode_keys, 
  100.                 16 };    /* MAXCOL in cmds.c */
  101.     static fdb modefdb = { _CMKEY, CM_NLH|KEY_WID, nil, (pdat) &modetab,
  102.                    "other mode, " };
  103.  
  104.     pval parseval;
  105.     fdb *used, *use;
  106.     int level, topval;            /* what we're giving help about */
  107.     char *topic;
  108.     char **topicfiles;
  109.     int mret, plen;
  110.     char mbuf[BUFSIZ];
  111.     static time_t topic_mtimes[3] = { 0, 0, 0 }; /* TOP, READ, SEND */
  112.     struct stat sbuf;
  113.     keytab * helpfiles_to_keytab();
  114.     static keywrd nulkwd[] = {
  115.     { "", 0, 0 }
  116.     };
  117.     static keytab nuldat = {0, nulkwd };
  118.     static keytab *topic_pdats[3] = { &nuldat, &nuldat, &nuldat };
  119.  
  120.     if (recurse == 0)
  121.     noise("me with");
  122.     else 
  123.     noise("subject");
  124.  
  125.     sprintf(mbuf, "%s/%s/%s", help_dir, TOPIC_DIR, help_subdirs[mode]);
  126.     if (stat(mbuf, &sbuf) < 0) {
  127.     topicfdb._cmdat = (pdat) topic_pdats[mode]; /* use old one */
  128.     fprintf(stderr,"?Could not find help directory\n");
  129.     }
  130.     else if (sbuf.st_mtime != topic_mtimes[mode]) {
  131.     sprintf(mbuf, "%s/%s/%s/*.HLP", 
  132.         help_dir, TOPIC_DIR, help_subdirs[mode]);
  133.     topic_mtimes[mode] = sbuf.st_mtime;
  134.     mret = match(mbuf, strlen(mbuf), &topic_filfdb, &parseval,
  135.              &used, &plen);
  136.     if (mret != CMxOK) {
  137.         topicfdb._cmdat = (pdat) topic_pdats[mode];
  138.         fprintf(stderr,"?Could not read help directory\n");
  139.     }
  140.     else {
  141.         if ((topicfdb._cmdat = (pdat) helpfiles_to_keytab(parseval._pvfil))
  142.         == NULL)
  143.         topicfdb._cmdat = (pdat) topic_pdats[mode]; /* use old one */
  144.         else {
  145.         if (topic_pdats[mode] != (keytab *)&nuldat)
  146.             free_ktab((keytab *) topic_pdats[mode]);
  147.         topic_pdats[mode] = (keytab *) topicfdb._cmdat; /* save new one */
  148.         }
  149.     }
  150.     }
  151.     else {                /* directory unchanged */
  152.     topicfdb._cmdat = (pdat) topic_pdats[mode];
  153.     }
  154.  
  155.     if (mode & MM_READ) {
  156.     use = fdbchn (&mm_read_fdb_abbr, &mm_read_fdb_1, 
  157.               &mm_read_fdb_2, &mm_read_fdb_3, &mm_read_fdb_4, 
  158.               &mm_read_fdb_5, &mm_read_fdb_6, &mm_read_fdb_7, 
  159.               &mm_read_fdb_inv, 
  160.               &shell_fdb, &topicfdb, &modefdb, &cfmfdb,NULL);
  161.     if (default_read_command[0] == '\0')
  162.         mm_read_fdb_abbr._cmdef = default_read_command;
  163.     level = HELP_READ;
  164.     }
  165.     else if (mode & MM_SEND) {
  166.     use = fdbchn (&mm_send_fdb_abbr, &mm_send_fdb_1, 
  167.               &mm_send_fdb_2, &mm_send_fdb_3, &mm_send_fdb_4, 
  168.               &mm_send_fdb_5, &mm_send_fdb_inv, 
  169.               &shell_fdb, &topicfdb, &modefdb, &cfmfdb,NULL);
  170.     if (default_send_command[0] == '\0')
  171.         mm_send_fdb_abbr._cmdef = default_send_command;
  172.     level = HELP_SEND;
  173.     }
  174.     else {                /* (mode & MM_TOP_LEVEL) */
  175.     use = fdbchn (&mm_top_fdb_abbr, &mm_top_fdb_1, &mm_top_fdb_2, 
  176.               &mm_top_fdb_3, &mm_top_fdb_4, &mm_top_fdb_5,
  177.               &mm_top_fdb_6, &mm_top_fdb_7, &mm_top_fdb_inv, 
  178.               &shell_fdb, &topicfdb, &modefdb, &cfmfdb,NULL);
  179.     level = HELP_TOP;
  180.     }
  181.  
  182.     parse(use,&parseval,&used);
  183.     if (used == &cfmfdb) {
  184.     printhelp ("mm", level, level);    /* general help */
  185.     return;
  186.     }
  187.     if (used == &shell_fdb) {
  188.     confirm();
  189.     printhelp ("shell", level, level);
  190.     return;
  191.     }
  192.     if (used == &modefdb) {
  193.     cmd_help_1(n, parseval._pvkey,recurse+1);
  194.     return;
  195.     }
  196.     topic = ((keywrd *) parseval._pvkey)->_kwkwd; /* which topic? */
  197.     topval = ((keywrd *)parseval._pvkey)->_kwval; /* what value returned? */
  198.     if (used == &topicfdb) {
  199.     confirm();
  200.     printhelp(topic, HELP_TOPIC, level);
  201.     return;
  202.     }
  203.     /* just commands left */
  204.     if ((topval != CMD_SET) && (topval != CMD_DEFINE)) {
  205.     confirm();
  206.     printhelp (topic, level, level);
  207.     }
  208.     if (topval == CMD_SET)        /* SET and DEFINE take sub-commands */
  209.     help_set(level);
  210.     else if (topval == CMD_DEFINE)
  211.     help_define(level);
  212. }
  213.  
  214.  
  215.  
  216.  
  217. /*
  218.  * printhelp:
  219.  * print specified help message, piping through pager when 
  220.  * appropriate
  221.  */
  222.  
  223. printhelp (command, level, topic_mode)
  224. int level;
  225. char *command;
  226. {
  227.     char fname[BUFSIZ];
  228.     struct stat sbuf;
  229.     int len;
  230.     char *msg;
  231.  
  232.     if (level > sizeof(help_subdirs)/sizeof(help_subdirs[0])) {
  233.     fprintf(stderr,"?Oops, invalid help request\n");
  234.     return;
  235.     }
  236.     if (level == HELP_TOPIC)
  237.     sprintf(fname,"%s/%s/%s/%s.HLP", 
  238.         help_dir, help_subdirs[level], help_subdirs[topic_mode], 
  239.         command);
  240.     else
  241.     sprintf(fname,"%s/%s/%s.HLP", help_dir, help_subdirs[level], command);
  242.     if (stat(fname, &sbuf) < 0) {
  243.     fprintf(stderr,"?Trouble finding help file: %s\n", fname);
  244.     return;
  245.     }
  246.     if ((helpfp = fopen(fname,"r")) == NULL) {
  247.     fprintf(stderr,"?Trouble reading help file: %s\n", fname);
  248.     return;
  249.     }
  250.     len = sbuf.st_size;
  251.  
  252.     if ((msg = (char *) malloc (len+1)) == NULL) {
  253.     fprintf (stderr, "?Out of memory\n"); /* XXX do something else? */
  254.     return;
  255.     }
  256.     if (fread (msg, sizeof (char), len, helpfp) != len) {
  257.     fprintf (stderr, "?Trouble reading help file - please report\n");
  258.     free (msg);
  259.     fclose(helpfp);
  260.     return;
  261.     }
  262.     msg[len] = '\0';            /* tie off with a null */
  263.     fclose(helpfp);
  264.     display_help(msg);
  265.     free (msg);
  266. }
  267.  
  268.  
  269. /*
  270.  * display_help:
  271.  * display a help message, piping through crt-filter when apporpriate
  272.  */
  273.  
  274. display_help (msg)
  275. char *msg;
  276. {
  277.     FILE *fp, *out, *more_pipe_open();
  278.     extern int use_crt_filter_always;
  279.  
  280.     out = cmcsb._cmoj ? cmcsb._cmoj : stdout;
  281.  
  282.     if (use_crt_filter_always ||
  283.     (logical_lines (msg, cmcsb._cmrmx) +1 >= cmcsb._cmrmx)) {
  284.     fp = more_pipe_open(out);
  285.     }
  286.     else
  287.     fp = out;            /* not long, just write it */
  288. #ifdef sun_stdio_bug
  289.     fwrite (msg, sizeof(char), strlen(msg), fp);
  290. #else
  291.     fputs (msg, fp);
  292. #endif /* sun_stdio_bug */
  293.     if (fp == out) {             /* not a pipe */
  294.     fflush (fp);
  295.     return;
  296.     }
  297.     more_pipe_close(fp);        /* really a pipe */
  298. }
  299.  
  300. /*
  301.  * help_set:
  302.  * give help on the various set variables, OR
  303.  * give general help on the set command
  304.  */
  305. help_set(level)
  306. int level;
  307. {
  308.     static fdb cfmfdb = { _CMCFM };
  309.     extern variable set_variables[];
  310.  
  311.     noise("variable");
  312.     parse (fdbchn(&cfmfdb,&set_cmd_fdb,nil), &pv, &used);
  313.     if (used == &cfmfdb) {
  314.     printhelp ("set", level, level);
  315.     return;
  316.     }
  317.     else {
  318.     int which = pv._pvkey;
  319.     confirm();
  320.     printhelp(set_variables[which].name, HELP_VARS, level);
  321. #ifdef undef
  322.     printf("\n\nThe current value of %s is: ", set_variables[which].name);
  323.     show_variable(stdout, which, false);
  324. #endif
  325.     }
  326.     return;
  327. }
  328.  
  329.  
  330. /*
  331.  * help_define:
  332.  * give help on specific aliases, or general help on define command
  333.  */
  334. help_define()
  335. {
  336.     keytab *mk_alias_keys(), *ak;
  337.     extern fdb aliasfdb;
  338.     static fdb cfmfdb = { _CMCFM };
  339.     pval pv;
  340.     fdb *used;
  341.  
  342.     ak = mk_alias_keys();
  343.     aliasfdb._cmdat = (pdat) ak;
  344.  
  345.     if (mail_aliases.count > 0)
  346.     parse(fdbchn(&cfmfdb, &aliasfdb, NULL), &pv, &used);
  347.     else
  348.     parse(fdbchn(&cfmfdb, nil), &pv, &used);
  349.     if (used == &cfmfdb) {
  350.     printhelp ("define", HELP_TOP, HELP_TOP);
  351.     return;
  352.     }
  353.     else {
  354.     int n = pv._pvkey;
  355.     confirm();
  356.     disp_alias(stdout, n, true,true);
  357.     return;
  358.     }
  359. }
  360.  
  361.  
  362.  
  363.  
  364. keytab *
  365. helpfiles_to_keytab(fl)
  366. char ** fl;
  367. {
  368.     char **k;
  369.     keytab *tab;
  370.     char *basename();
  371.     int i,len;
  372.  
  373.  
  374.     tab = (keytab *) malloc (sizeof(keytab));
  375.     for(len = 0, k = fl; k && *k; k++, len++);
  376.     if (len > 0)
  377.     tab->_ktwds = (keywrd *)malloc(len * sizeof(keywrd));
  378.     else tab->_ktwds = nil;
  379.     for(i = 0; i < len; i++) {
  380.     tab->_ktwds[i]._kwkwd = basename(fl[i]);
  381.     tab->_ktwds[i]._kwflg = 0;
  382.     tab->_ktwds[i]._kwval = i;
  383.     }
  384.     tab->_ktcnt = len;
  385.     return(tab);
  386. }
  387.  
  388. static char *
  389. basename(fn)
  390. char *fn;
  391. {
  392.     char *cp1, *cp2;
  393.     char *bp;
  394.     int len;
  395.  
  396.     if ((cp1 = rindex(fn,'/')) == NULL) 
  397.     cp1 = fn;
  398.     else
  399.     cp1++;
  400.     if ((cp2 = index(cp1,'.')) == NULL) 
  401.         cp2 = cp1 + strlen(cp1);
  402.     len = cp2 - cp1;
  403.     bp = (char *) malloc(len + 1);
  404.     strncpy(bp, cp1, len);
  405.     bp[len] = '\0';
  406.     return(bp);
  407. }
  408.  
  409.  
  410. free_ktab(tab)
  411. keytab *tab;
  412. {
  413.     int i;
  414.  
  415.     if (tab != nil) {
  416.     if (tab->_ktwds) {
  417.         for(i = 0; i < tab->_ktcnt; i++) {
  418.         free(tab->_ktwds[i]._kwkwd);
  419.         }
  420.         free(tab->_ktwds);
  421.     }
  422.     free(tab);
  423.     }
  424. }
  425.